#include "DmMainAfx.h"

#include "xGraphic_Type.h"
#include "xGraphic_Init.h"

#include "AlphaBltImpl.h"
#include "AlphaMixImp.h"

#include "StretchTable.h"
#include "Blend.h"

#include "GrayPalette.h"

namespace xRender
{

BlendFunc BlendSrc[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcOver[MAX_NUM_BITSPIXEL];
BlendFunc BlendDstOver[MAX_NUM_BITSPIXEL];
BlendFunc BlendMul[MAX_NUM_BITSPIXEL];
BlendKeyColorFunc BlendKeyColor[MAX_NUM_BITSPIXEL];
BlendAlphaFunc BlendAlpha[MAX_NUM_BITSPIXEL];

BlendFunc BlendSrcStretch[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcOverStretch[MAX_NUM_BITSPIXEL];
BlendFunc BlendDstOverStretch[MAX_NUM_BITSPIXEL];
BlendFunc BlendMulStretch[MAX_NUM_BITSPIXEL];
BlendKeyColorFunc BlendKeyColorStretch[MAX_NUM_BITSPIXEL];
BlendAlphaFunc BlendAlphaStretch[MAX_NUM_BITSPIXEL];

BlendClipFunc BlendSrcStretchClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendSrcOverStretchClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendDstOverStretchClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendMulStretchClip[MAX_NUM_BITSPIXEL];
BlendKeyColorClipFunc BlendKeyColorStretchClip[MAX_NUM_BITSPIXEL];
BlendAlphaClipFunc BlendAlphaStretchClip[MAX_NUM_BITSPIXEL];

BlendFunc BlendSrcStretchBilinear[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcOverStretchBilinear[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcStretchBicubic[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcOverStretchBicubic[MAX_NUM_BITSPIXEL];
BlendFunc BlendSrcStretchAreaAveraging[MAX_NUM_BITSPIXEL];
BlendAlphaFunc BlendAlphaStretchBilinear[MAX_NUM_BITSPIXEL];
BlendAlphaFunc BlendAlphaStretchBicubic[MAX_NUM_BITSPIXEL];

BlendClipFunc BlendSrcStretchBilinearClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendSrcOverStretchBilinearClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendSrcStretchBicubicClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendSrcOverStretchBicubicClip[MAX_NUM_BITSPIXEL];
BlendClipFunc BlendSrcStretchAreaAveragingClip[MAX_NUM_BITSPIXEL];
BlendAlphaClipFunc BlendAlphaStretchBilinearClip[MAX_NUM_BITSPIXEL];
BlendAlphaClipFunc BlendAlphaStretchBicubicClip[MAX_NUM_BITSPIXEL];

BlendColorFunc BlendSrcColor;
BlendColorFunc BlendSrcOverColor;
BlendColorFunc BlendDstOverColor;
BlendColorFunc BlendMulColor;
BlendColorFunc BlendOrColor;
BlendColorFunc BlendGrayColor;

BlendAlphaBltFunc BlendAlphaBlt;
BlendAlphaBltWithConstantAlphaFunc BlendAlphaBltWithConstantAlpha;
BlendAlphaBltFunc BlendAlphaBltStretch;
BlendAlphaBltWithConstantAlphaFunc BlendAlphaBltStretchWithConstantAlpha;

BlendAlphaMixFunc BlendAlphaMix;
BlendAlphaMixFunc BlendAlphaMixStretch;
BlendAlphaMixColorFunc BlendAlphaMixColor;

static CInit init;

CInit::CInit()
{
    xCPUInfo::CheckCPUID();
    InitStretchTable();
    if (!xCPUInfo::IsSupportMMX())
    {
        InitColorTable();
    }
    InitGrayPalette();

    //8
    BlendSrc[BITS_8] = BlendSrc8;
    BlendSrcOver[BITS_8] = BlendSrcOver8;
    BlendDstOver[BITS_8] = BlendDstOver8;
    BlendMul[BITS_8] = BlendMul8;
    BlendKeyColor[BITS_8] = BlendSrc8;
    BlendAlpha[BITS_8] = BlendSrcOver8;

    BlendSrcStretch[BITS_8] = BlendSrc8Stretch;
    BlendSrcOverStretch[BITS_8] = BlendSrcOver8Stretch;
    BlendDstOverStretch[BITS_8] = BlendDstOver8Stretch;
    BlendMulStretch[BITS_8] = BlendMul8Stretch;
    BlendKeyColorStretch[BITS_8] = BlendSrc8Stretch;
    BlendAlphaStretch[BITS_8] = BlendSrcOver8Stretch;

    BlendSrcStretchClip[BITS_8] = BlendSrc8Stretch;
    BlendSrcOverStretchClip[BITS_8] = BlendSrcOver8Stretch;
    BlendDstOverStretchClip[BITS_8] = BlendDstOver8Stretch;
    BlendMulStretchClip[BITS_8] = BlendMul8Stretch;
    BlendKeyColorStretchClip[BITS_8] = BlendSrc8Stretch;
    BlendAlphaStretchClip[BITS_8] = BlendSrcOver8Stretch;

    BlendSrcStretchBilinear[BITS_8] = BlendSrc8StretchBilinear;
    BlendSrcOverStretchBilinear[BITS_8] = BlendSrcOver8StretchBilinear;
    BlendSrcStretchBilinearClip[BITS_8] = BlendSrc8StretchBilinear;
    BlendSrcOverStretchBilinearClip[BITS_8] = BlendSrcOver8StretchBilinear;
    BlendSrcStretchBicubic[BITS_8] = BlendSrc8StretchBicubic;
    BlendSrcOverStretchBicubic[BITS_8] = BlendSrcOver8StretchBicubic;
    BlendSrcStretchBicubicClip[BITS_8] = BlendSrc8StretchBicubic;
    BlendSrcOverStretchBicubicClip[BITS_8] = BlendSrcOver8StretchBicubic;

    BlendAlphaStretchBilinear[BITS_8] = BlendSrcOver8StretchBilinear;
    BlendAlphaStretchBilinearClip[BITS_8] = BlendSrcOver8StretchBilinear;
    BlendAlphaStretchBicubic[BITS_8] = BlendSrcOver8StretchBicubic;
    BlendAlphaStretchBicubicClip[BITS_8] = BlendSrcOver8StretchBicubic;

    BlendSrcStretchAreaAveraging[BITS_8] = BlendSrc8StretchAreaAveraging;
    BlendSrcStretchAreaAveragingClip[BITS_8] = BlendSrc8StretchAreaAveraging;

    //24
    BlendSrc[BITS_24] = BlendSrc24;
    BlendSrcOver[BITS_24] = BlendSrcOver24;
    BlendDstOver[BITS_24] = BlendDstOver24;
    BlendMul[BITS_24] = BlendMul24;
    BlendKeyColor[BITS_24] = BlendSrc24;
    BlendAlpha[BITS_24] = BlendSrcOver24;

    BlendSrcStretch[BITS_24] = BlendSrc24Stretch;
    BlendSrcOverStretch[BITS_24] = BlendSrcOver24Stretch;
    BlendDstOverStretch[BITS_24] = BlendDstOver24Stretch;
    BlendMulStretch[BITS_24] = BlendMul24Stretch;
    BlendKeyColorStretch[BITS_24] = BlendSrc24Stretch;
    BlendAlphaStretch[BITS_24] = BlendSrcOver24Stretch;

    BlendSrcStretchClip[BITS_24] = BlendSrc24Stretch;
    BlendSrcOverStretchClip[BITS_24] = BlendSrcOver24Stretch;
    BlendDstOverStretchClip[BITS_24] = BlendDstOver24Stretch;
    BlendMulStretchClip[BITS_24] = BlendMul24Stretch;
    BlendKeyColorStretchClip[BITS_24] = BlendSrc24Stretch;
    BlendAlphaStretchClip[BITS_24] = BlendSrcOver24Stretch;

    BlendSrcStretchBilinear[BITS_24] = BlendSrc24StretchBilinear;
    BlendSrcOverStretchBilinear[BITS_24] = BlendSrcOver24StretchBilinear;
    BlendSrcStretchBilinearClip[BITS_24] = BlendSrc24StretchBilinear;
    BlendSrcOverStretchBilinearClip[BITS_24] = BlendSrcOver24StretchBilinear;
    BlendSrcStretchBicubic[BITS_24] = BlendSrc24StretchBicubic;
    BlendSrcOverStretchBicubic[BITS_24] = BlendSrcOver24StretchBicubic;
    BlendSrcStretchBicubicClip[BITS_24] = BlendSrc24StretchBicubic;
    BlendSrcOverStretchBicubicClip[BITS_24] = BlendSrcOver24StretchBicubic;

    BlendAlphaStretchBilinear[BITS_24] = BlendSrcOver24StretchBilinear;
    BlendAlphaStretchBilinearClip[BITS_24] = BlendSrcOver24StretchBilinear;
    BlendAlphaStretchBicubic[BITS_24] = BlendSrcOver24StretchBicubic;
    BlendAlphaStretchBicubicClip[BITS_24] = BlendSrcOver24StretchBicubic;

    BlendSrcStretchAreaAveraging[BITS_24] = BlendSrc24StretchAreaAveraging;
    BlendSrcStretchAreaAveragingClip[BITS_24] = BlendSrc24StretchAreaAveraging;

    //32
    BlendSrc[BITS_32] = BlendSrc32;
    BlendSrcOver[BITS_32] = BlendSrcOver32;
    BlendDstOver[BITS_32] = BlendDstOver32;
    BlendMul[BITS_32] = BlendMul32;
    BlendKeyColor[BITS_32] = BlendSrc32;
    BlendAlpha[BITS_32] = BlendSrcOver32;

    BlendSrcStretch[BITS_32] = BlendSrc32Stretch;
    BlendSrcOverStretch[BITS_32] = BlendSrcOver32Stretch;
    BlendDstOverStretch[BITS_32] = BlendDstOver32Stretch;
    BlendMulStretch[BITS_32] = BlendMul32Stretch;
    BlendKeyColorStretch[BITS_32] = BlendSrc32Stretch;
    BlendAlphaStretch[BITS_32] = BlendSrcOver32Stretch;

    BlendSrcStretchClip[BITS_32] = BlendSrc32Stretch;
    BlendSrcOverStretchClip[BITS_32] = BlendSrcOver32Stretch;
    BlendDstOverStretchClip[BITS_32] = BlendDstOver32Stretch;
    BlendMulStretchClip[BITS_32] = BlendMul32Stretch;
    BlendKeyColorStretchClip[BITS_32] = BlendSrc32Stretch;
    BlendAlphaStretchClip[BITS_32] = BlendSrcOver32Stretch;

    BlendSrcStretchBilinear[BITS_32] = BlendSrc32StretchBilinear;
    BlendSrcOverStretchBilinear[BITS_32] = BlendSrcOver32StretchBilinear;
    BlendSrcStretchBilinearClip[BITS_32] = BlendSrc32StretchBilinear;
    BlendSrcOverStretchBilinearClip[BITS_32] = BlendSrcOver32StretchBilinear;
    BlendSrcStretchBicubic[BITS_32] = BlendSrc32StretchBicubic;
    BlendSrcOverStretchBicubic[BITS_32] = BlendSrcOver32StretchBicubic;
    BlendSrcStretchBicubicClip[BITS_32] = BlendSrc32StretchBicubic;
    BlendSrcOverStretchBicubicClip[BITS_32] = BlendSrcOver32StretchBicubic;

    BlendAlphaStretchBilinear[BITS_32] = BlendSrcOver32StretchBilinear;
    BlendAlphaStretchBilinearClip[BITS_32] = BlendSrcOver32StretchBilinear;
    BlendAlphaStretchBicubic[BITS_32] = BlendSrcOver32StretchBicubic;
    BlendAlphaStretchBicubicClip[BITS_32] = BlendSrcOver32StretchBicubic;

    BlendSrcStretchAreaAveraging[BITS_32] = BlendSrc32StretchAreaAveraging;
    BlendSrcStretchAreaAveragingClip[BITS_32] = BlendSrc32StretchAreaAveraging;

    BlendSrcColor = BlendSrcColor32;
    BlendSrcOverColor = BlendSrcOverColor32;
    BlendDstOverColor = BlendDstOverColor32;
    BlendMulColor = BlendMulColor32;
    BlendOrColor = BlendOrColor32;
    BlendGrayColor = BlendGrayColor32;

    BlendAlphaBlt = AlphaBlt;
    BlendAlphaBltWithConstantAlpha = AlphaBlt;
    BlendAlphaBltStretch = AlphaBltStretch;
    BlendAlphaBltStretchWithConstantAlpha = AlphaBltStretch;

    BlendAlphaMix = AlphaMix;
    BlendAlphaMixStretch = AlphaMixStretch;
    BlendAlphaMixColor = AlphaMix;

    if (xCPUInfo::IsSupportMMX())
    {
        //8
        BlendSrc[BITS_8] = BlendSrc8MMX;
        BlendSrcOver[BITS_8] = BlendSrcOver8MMX;
        BlendDstOver[BITS_8] = BlendDstOver8MMX;
        BlendMul[BITS_8] = BlendMul8MMX;
        BlendKeyColor[BITS_8] = BlendSrc8MMX;
        BlendAlpha[BITS_8] = BlendSrcOver8MMX;

        BlendSrcStretch[BITS_8] = BlendSrc8StretchMMX;
        BlendSrcOverStretch[BITS_8] = BlendSrcOver8StretchMMX;
        BlendDstOverStretch[BITS_8] = BlendDstOver8StretchMMX;
        BlendMulStretch[BITS_8] = BlendMul8StretchMMX;
        BlendKeyColorStretch[BITS_8] = BlendSrc8StretchMMX;
        BlendAlphaStretch[BITS_8] = BlendSrcOver8StretchMMX;

        BlendSrcStretchClip[BITS_8] = BlendSrc8StretchMMX;
        BlendSrcOverStretchClip[BITS_8] = BlendSrcOver8StretchMMX;
        BlendDstOverStretchClip[BITS_8] = BlendDstOver8StretchMMX;
        BlendMulStretchClip[BITS_8] = BlendMul8StretchMMX;
        BlendKeyColorStretchClip[BITS_8] = BlendSrc8StretchMMX;
        BlendAlphaStretchClip[BITS_8] = BlendSrcOver8StretchMMX;

        BlendSrcStretchBilinear[BITS_8] = BlendSrc8StretchBilinearMMX;
        BlendSrcOverStretchBilinear[BITS_8] = BlendSrcOver8StretchBilinearMMX;
        BlendSrcStretchBilinearClip[BITS_8] = BlendSrc8StretchBilinearMMX;
        BlendSrcOverStretchBilinearClip[BITS_8] = BlendSrcOver8StretchBilinearMMX;
        BlendSrcStretchBicubic[BITS_8] = BlendSrc8StretchBicubicMMX;
        BlendSrcOverStretchBicubic[BITS_8] = BlendSrcOver8StretchBicubicMMX;
        BlendSrcStretchBicubicClip[BITS_8] = BlendSrc8StretchBicubicMMX;
        BlendSrcOverStretchBicubicClip[BITS_8] = BlendSrcOver8StretchBicubicMMX;

        BlendAlphaStretchBilinear[BITS_8] = BlendSrcOver8StretchBilinearMMX;
        BlendAlphaStretchBilinearClip[BITS_8] = BlendSrcOver8StretchBilinearMMX;
        BlendAlphaStretchBicubic[BITS_8] = BlendSrcOver8StretchBicubicMMX;
        BlendAlphaStretchBicubicClip[BITS_8] = BlendSrcOver8StretchBicubicMMX;

        //24
        BlendSrc[BITS_24] = BlendSrc24MMX;
        BlendSrcOver[BITS_24] = BlendSrcOver24MMX;
        BlendDstOver[BITS_24] = BlendDstOver24MMX;
        BlendMul[BITS_24] = BlendMul24MMX;
        BlendKeyColor[BITS_24] = BlendSrc24MMX;
        BlendAlpha[BITS_24] = BlendSrcOver24MMX;

        BlendSrcStretch[BITS_24] = BlendSrc24StretchMMX;
        BlendSrcOverStretch[BITS_24] = BlendSrcOver24StretchMMX;
        BlendDstOverStretch[BITS_24] = BlendDstOver24StretchMMX;
        BlendMulStretch[BITS_24] = BlendMul24StretchMMX;
        BlendKeyColorStretch[BITS_24] = BlendSrc24StretchMMX;
        BlendAlphaStretch[BITS_24] = BlendSrcOver24StretchMMX;

        BlendSrcStretchClip[BITS_24] = BlendSrc24StretchMMX;
        BlendSrcOverStretchClip[BITS_24] = BlendSrcOver24StretchMMX;
        BlendDstOverStretchClip[BITS_24] = BlendDstOver24StretchMMX;
        BlendMulStretchClip[BITS_24] = BlendMul24StretchMMX;
        BlendKeyColorStretchClip[BITS_24] = BlendSrc24StretchMMX;
        BlendAlphaStretchClip[BITS_24] = BlendSrcOver24StretchMMX;

        BlendSrcStretchBilinear[BITS_24] = BlendSrc24StretchBilinearMMX;
        BlendSrcOverStretchBilinear[BITS_24] = BlendSrcOver24StretchBilinearMMX;
        BlendSrcStretchBilinearClip[BITS_24] = BlendSrc24StretchBilinearMMX;
        BlendSrcOverStretchBilinearClip[BITS_24] = BlendSrcOver24StretchBilinearMMX;
        BlendSrcStretchBicubic[BITS_24] = BlendSrc24StretchBicubicMMX;
        BlendSrcOverStretchBicubic[BITS_24] = BlendSrcOver24StretchBicubicMMX;
        BlendSrcStretchBicubicClip[BITS_24] = BlendSrc24StretchBicubicMMX;
        BlendSrcOverStretchBicubicClip[BITS_24] = BlendSrcOver24StretchBicubicMMX;

        BlendAlphaStretchBilinear[BITS_24] = BlendSrcOver24StretchBilinearMMX;
        BlendAlphaStretchBilinearClip[BITS_24] = BlendSrcOver24StretchBilinearMMX;
        BlendAlphaStretchBicubic[BITS_24] = BlendSrcOver24StretchBicubicMMX;
        BlendAlphaStretchBicubicClip[BITS_24] = BlendSrcOver24StretchBicubicMMX;

        //32
        BlendSrc[BITS_32] = BlendSrc32MMX;
        BlendSrcOver[BITS_32] = BlendSrcOver32MMX;
        BlendDstOver[BITS_32] = BlendDstOver32MMX;
        BlendMul[BITS_32] = BlendMul32MMX;
        BlendKeyColor[BITS_32] = BlendSrc32MMX;
        BlendAlpha[BITS_32] = BlendSrcOver32MMX;

        BlendSrcStretch[BITS_32] = BlendSrc32StretchMMX;
        BlendSrcOverStretch[BITS_32] = BlendSrcOver32StretchMMX;
        BlendDstOverStretch[BITS_32] = BlendDstOver32StretchMMX;
        BlendMulStretch[BITS_32] = BlendMul32StretchMMX;
        BlendKeyColorStretch[BITS_32] = BlendSrc32StretchMMX;
        BlendAlphaStretch[BITS_32] = BlendSrcOver32StretchMMX;

        BlendSrcStretchClip[BITS_32] = BlendSrc32StretchMMX;
        BlendSrcOverStretchClip[BITS_32] = BlendSrcOver32StretchMMX;
        BlendDstOverStretchClip[BITS_32] = BlendDstOver32StretchMMX;
        BlendMulStretchClip[BITS_32] = BlendMul32StretchMMX;
        BlendKeyColorStretchClip[BITS_32] = BlendSrc32StretchMMX;
        BlendAlphaStretchClip[BITS_32] = BlendSrcOver32StretchMMX;

        BlendSrcStretchBilinear[BITS_32] = BlendSrc32StretchBilinearMMX;
        BlendSrcOverStretchBilinear[BITS_32] = BlendSrcOver32StretchBilinearMMX;
        BlendSrcStretchBilinearClip[BITS_32] = BlendSrc32StretchBilinearMMX;
        BlendSrcOverStretchBilinearClip[BITS_32] = BlendSrcOver32StretchBilinearMMX;
        BlendSrcStretchBicubic[BITS_32] = BlendSrc32StretchBicubicMMX;
        BlendSrcOverStretchBicubic[BITS_32] = BlendSrcOver32StretchBicubicMMX;
        BlendSrcStretchBicubicClip[BITS_32] = BlendSrc32StretchBicubicMMX;
        BlendSrcOverStretchBicubicClip[BITS_32] = BlendSrcOver32StretchBicubicMMX;

        BlendAlphaStretchBilinear[BITS_32] = BlendSrcOver32StretchBilinearMMX;
        BlendAlphaStretchBilinearClip[BITS_32] = BlendSrcOver32StretchBilinearMMX;
        BlendAlphaStretchBicubic[BITS_32] = BlendSrcOver32StretchBicubicMMX;
        BlendAlphaStretchBicubicClip[BITS_32] = BlendSrcOver32StretchBicubicMMX;

        BlendSrcColor = BlendSrcColor32MMX;
        BlendSrcOverColor = BlendSrcOverColor32MMX;
        BlendDstOverColor = BlendDstOverColor32MMX;
        BlendMulColor = BlendMulColor32MMX;
        BlendOrColor = BlendOrColor32MMX;

        BlendAlphaMix = AlphaMixMMX;
        BlendAlphaMixStretch = AlphaMixStretchMMX;
        BlendAlphaMixColor = AlphaMixMMX;
    }

    if (xCPUInfo::IsSupportSSE())
    {
        BlendSrc[BITS_32] = BlendSrc32SSE;

        BlendSrcColor = BlendSrcColor32SSE;
        BlendOrColor = BlendOrColor32SSE;

        BlendAlphaBltWithConstantAlpha = AlphaBltSSE;
        BlendAlphaBltStretchWithConstantAlpha = AlphaBltStretchSSE;
    }

    if (xCPUInfo::IsSupportSSE2())
    {
        BlendSrc[BITS_32] = BlendSrc32SSE2;

        BlendSrcStretchAreaAveraging[BITS_8] = BlendSrc8StretchAreaAveragingSSE2;
        BlendSrcStretchAreaAveragingClip[BITS_8] = BlendSrc8StretchAreaAveragingSSE2;

        BlendSrcStretchAreaAveraging[BITS_24] = BlendSrc24StretchAreaAveragingSSE2;
        BlendSrcStretchAreaAveragingClip[BITS_24] = BlendSrc24StretchAreaAveragingSSE2;

        BlendSrcStretchAreaAveraging[BITS_32] = BlendSrc32StretchAreaAveragingSSE2;
        BlendSrcStretchAreaAveragingClip[BITS_32] = BlendSrc32StretchAreaAveragingSSE2;
    }

}

}